|
|
|
|
|
|
|
Dim dwRead As Long
Dim dwNeeded As Long
Dim cRecords As Long
Dim dwThisRecord As Long |
|
|
|
|
|
|
|
|
Now, the catch is this: Once we load a buffer with one or more of these structure-plus-data combinations, how do we extract the information using Visual Basic? |
|
|
|
|
|
|
|
|
Well, the first step is to get access to the structure data. The easiest way to do this is to define a temporary EVENTLOGRECORD structure to hold the data. We'll load it from the buffer using the following memory copy routine: |
|
|
|
|
|
|
|
|
Private Declare Sub RtlMoveMemory Lib "kernel32" (dest As Any, _
source As Any, ByVal bytes As Long) |
|
|
|
|
|
|
|
|
See those As Any parameters? They imply that the function can handle any type of parameter. Because the purpose of this function is to copy a block of memory from one location to another, this makes the function extremely dangerous. Any mistake is likely to corrupt memory or raise a memory exception. We also need a pointer variable. Because Visual Basic does not support pointers directly, we'll use a Long variable. This implies two variables: |
|
|
|
|
|
|
|
|
Dim ev As EVENTLOGRECORD
Dim pevlr As Long |
|
|
|
|
|
|
|
|
The C language allows you to access data using pointers and to convert pointers from one type to another using a technique called "casting." We'll fake this process in Visual Basic by copying data into a user-defined type, as follows: |
|
|
|
|
|
|
|
|
pevlr = VarPtr(bBuffer(0))
RtlMoveMemory ev, ByVal pevlr, Len(EVENTLOGRECORD) |
|
|
|
|
|
|
|
|
The VarPtr operator is an undocumented operator built into Visual Basic to obtain the address of a variable. We actually obtain the address of the first byte, because it appears (by definition) at the start of the buffer. Note how it must be passed by value to the RtlMoveMemory function. If you passed it by reference, you would pass the address of the pevlr variable, not the address of the bBuffer array. |
|
|
|
|
|
|
|
|
Now that we've copied the data into the temporary ev structure, you can access the event data. But how do we get the string data that follows the EVENTLOGRECORD structure in the buffer? To do this, we'll need two more API functions, lstrlen and lstrcpy, which are declared as follows: |
|
|
|
|
|
|
|
|
Declare Function lstrlenptr Lib "kernel32" Alias "lstrlenA" _ |
|
|
|
|
|